#ifndef _INCLUDE_LOOPSYS_H
#define _INCLUDE_LOOPSYS_H

#include <stdint.h>

/********************LOOPSYS Configuration START********************/

#define LOOPSYS_ENABLE_SYSTIME
#define LOOPSYS_ENABLE_TASK_AUTORUN
#define LOOPSYS_ENABLE_TASK_TIMER
#define LOOPSYS_ENABLE_TASK_MSG
#define LOOPSYS_ENABLE_EVENT_AUTO_CLEAR
#define LOOPSYS_ENABLE_ASSERT

#ifdef LOOPSYS_ENABLE_TASK_TIMER
    #ifndef LOOPSYS_ENABLE_SYSTIME
    #error "Timer task depends on systime. Please enable systime!"
    #endif
#endif

#define LOOPSYS_TICK_FREQ    1000
#define LOOPSYS_TASK_NUM     12
#define LOOPSYS_MSG_NUM      8
#define LOOPSYS_MSG_BUF_SIZE 2

/********************LOOPSYS Configuration END********************/

#define LOOPSYS_OK   0
#define LOOPSYS_ERR  1

#ifdef LOOPSYS_ENABLE_ASSERT
#include "log.h"
#define LOOPSYS_ASSERT(cond)\
do                                                                                             \
{                                                                                              \
    if (!(cond))                                                                               \
    {                                                                                          \
        LOGE("Assert failed. Condition(%s). [%s][%d]\r\n", #cond, __FUNCTION__, __LINE__);     \
        while(1);                                                                              \
    }                                                                                          \
}while(0)
#else
#define LOOPSYS_ASSERT(cond)
#endif

#define LOOPSYS_TIMER_FOREVER    0xFFFFFFFF
#define LOOPSYS_EVENT_TIMEOUT    0x80000000
#define LOOPSYS_EVENT_AUTORUN    0x40000000
#define LOOPSYS_EVENT_MSG        0x20000000
#define LOOPSYS_EVENT_SYS_ALL    0xF0000000
#define LOOPSYS_EVENT_MASK       0x0FFFFFFF

typedef struct loop_task loop_task_t;
typedef void (*idle_hook_t)(void);
typedef void (*task_func_t)(loop_task_t *self, uint32_t events);

#ifdef LOOPSYS_ENABLE_TASK_TIMER
typedef struct loop_timer
{
    uint8_t  on;
    uint32_t repeat;
    uint32_t period;
    uint32_t timeout;
}loop_timer_t;
#endif

#ifdef LOOPSYS_ENABLE_TASK_MSG
struct loop_task;
typedef struct loop_msg
{
    uint8_t id;
    void   *data;
    loop_task_t *publisher;   
}loop_msg_t;
#endif

struct loop_task
{
    uint8_t priority;
    uint8_t active;
    uint8_t mode;
    uint32_t events;
    task_func_t  func;
#ifdef LOOPSYS_ENABLE_TASK_TIMER
    loop_timer_t timer;
#endif
#ifdef LOOPSYS_ENABLE_TASK_MSG
    uint32_t msg_sub;
    uint8_t  msg_cnt;
    loop_msg_t msg[LOOPSYS_MSG_BUF_SIZE];
#endif
};


#ifdef LOOPSYS_ENABLE_SYSTIME
void loopsys_tick_increase(void);
uint32_t loopsys_ms_to_tick(uint32_t ms);
uint32_t loopsys_tick_to_ms(uint32_t tick);
uint32_t loopsys_systime_get_tick(void);
uint32_t loopsys_systime_get_ms(void);
void loopsys_delay_tick(uint32_t us);
void loopsys_delay_ms(uint32_t ms);
#endif


loop_task_t *loopsys_task_find(uint8_t prio);
loop_task_t *loopsys_task_add(uint8_t prio, task_func_t func);
void loopsys_task_del(loop_task_t *task);

#ifdef LOOPSYS_ENABLE_TASK_TIMER
void loopsys_task_timer_enable(loop_task_t *task, uint32_t repeat, uint32_t period);
void loopsys_task_timer_disable(loop_task_t *task);
void loopsys_task_timer_start(loop_task_t *task);
void loopsys_task_timer_stop(loop_task_t *task);
#endif

#ifdef LOOPSYS_ENABLE_TASK_AUTORUN
void loopsys_task_autorun_enable(loop_task_t *task);
void loopsys_task_autorun_disable(loop_task_t *task);
#endif

#ifdef LOOPSYS_ENABLE_TASK_MSG
void loopsys_msg_publish(loop_task_t *pub, uint8_t id, void *data);
void loopsys_msg_subscribe(loop_task_t *sub, uint8_t id);
void loopsys_msg_unsubscribe(loop_task_t *sub, uint8_t id);
int32_t loopsys_msg_get(loop_task_t *sub, loop_msg_t **msg);
#endif

void loopsys_event_send(loop_task_t *task, uint32_t event);
void loopsys_event_clear(loop_task_t *task, uint32_t event);
void loopsys_event_clear_all(loop_task_t *task);

void loopsys_set_idle_hook(idle_hook_t hook);

void loopsys_run(void);

#endif//_INCLUDE_LOOPSYS_H
